package com.accounting.client.frontend.product;

import java.util.ArrayList;
import java.util.List;

import com.accounting.client.frontend.product.handlers.CreateProductCatalogHandler;
import com.accounting.client.frontend.product.handlers.CreateProductHandler;
import com.accounting.client.frontend.product.handlers.UpdateProductCatalogHandler;
import com.accounting.client.frontend.product.handlers.UpdateProductHandler;
import com.accounting.client.frontend.product.tree.ProductCatalogTree;
import com.accounting.client.frontend.product.tree.ProductCatalogTreeUtil;
import com.accounting.client.remote.Services;
import com.accounting.client.remote.enumeration.UserRole;
import com.accounting.client.remote.obj.Product;
import com.accounting.client.remote.obj.ProductCatalog;
import com.accounting.client.resource.BoxResources;
import com.accounting.client.session.ErrorHandler;
import com.accounting.client.session.Session;
import com.accounting.client.session.SessionManager;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;

import corelib.client.collection.TreeVisitor;
import corelib.client.delegate.Action;
import corelib.client.delegate.DataCallback;
import corelib.client.resource.CommonResources;
import corelib.client.schedule.DeferredTask;
import corelib.client.search.PagingRequest;
import corelib.client.search.PagingResult;
import corelib.client.ui.SimpleModal;
import corelib.client.ui.widget.SimpleDataModel;
import corelib.client.ui.widget.WidgetListener;
import corelib.client.ui.widget.dialog.SimpleDialog;
import corelib.client.ui.widget.grid.SimpleDataGrid;
import corelib.client.ui.widget.grid.SimpleDataGridHandler;
import corelib.client.ui.widget.grid.cell.CellRenderer;
import corelib.client.ui.widget.grid.column.ColumnConfig;
import corelib.client.ui.widget.grid.column.ColumnConfigs;
import corelib.client.ui.widget.messagebox.SimpleMessageBox;
import corelib.client.ui.widget.page.PageBase;
import corelib.client.ui.widget.panel.SimpleLayoutPanel;
import corelib.client.ui.widget.toolbar.SimpleRibbon;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton;
import corelib.client.ui.widget.toolbar.SimpleRibbonButton.ButtonSize;
import corelib.client.ui.widget.tree.SimpleTreeNode;

public class ProductManager extends PageBase<Widget> {
	
	private final static int MaxRecordsPerPage  = 20;
	private final static int PRODUCT_CATALOG_ID = 27;
	
	private int currentOffset = 0;
	private int currentRecordsPerPage = 0;
	
	private ProductCatalogTree 		catalogs;
	private ProductTableHandler     productTableHandler;
	private SimpleDataGrid<Product> productTable;
	private SimpleRibbonButton 		deleteCatalogBtn;
	private SimpleRibbonButton 		updateCatalogBtn;
	private SimpleRibbonButton 		addProductBtn;
	private SimpleRibbonButton 		deleteProductBtn;
	private SimpleRibbonButton 		updateProductBtn;
	private SimpleRibbonButton 		refreshProductBtn;
	private SimpleRibbonButton 		nextBtn;
	private SimpleRibbonButton 		previousBtn;
	private SimpleRibbon 			toolBar;
	
	private SplitLayoutPanel contentPanel;
	
	public ProductManager() {
		setPageName("产品管理");
		setPageIcon(BoxResources.INSTANCE.product24());
	}

	@Override
	protected Widget createWidget() {
		toolBar = createToolBar();
		contentPanel = createContentPanel();
		SimpleLayoutPanel panel = new SimpleLayoutPanel();
		panel.add(toolBar);
		panel.add(contentPanel);
		panel.setWidgetTopHeight(toolBar, 0, Unit.PX, 80, Unit.PX);
		panel.setWidgetTopBottom(contentPanel, 80, Unit.PX, 0, Unit.PX);
		return panel;
	}

	@Override
	protected void afterCreateWidget(Widget widgetCreated) {
		super.afterCreateWidget(widgetCreated);
		new DeferredTask().run(new ScheduledCommand(){
			@Override
			public void execute() {
				loadCatalogs();
				loadProducts(PRODUCT_CATALOG_ID, currentOffset);
			}
		}, 500);
	}
	
	public SimpleDataGrid<Product> getProductTable() {
		return this.productTable;
	}

	protected SimpleRibbon createToolBar() {
		SimpleRibbon toolBar = new SimpleRibbon();
		if (Session.Current.getRole() == UserRole.SUPER){
			createProductCatalogButtons(toolBar);
			toolBar.addSeparator(ButtonSize.Medium);
		}
		
		toolBar.addPushButton(addProductBtn = new SimpleRibbonButton("增加产品",
			BoxResources.INSTANCE.addProduct32(),ButtonSize.Medium,
			new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					final ProductCatalog info = catalogs.getSelectedCatalog();
					if (info != null) {
						SimpleDialog.show(new CreateProductHandler(info,new Action(){
							@Override
							public void run() {
								loadProducts(info.getId(), currentOffset);
							}
						}));
					}
				}
			}
		));
		toolBar.addPushButton(deleteProductBtn = new SimpleRibbonButton("删除产品",
				BoxResources.INSTANCE.deleteProduct32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						Product product = productTable.getSelectedObject();
						if (product == null){
							return;
						}
						
						SimpleMessageBox.confirm("Delete " + product.getCName(), "Are you sure to delete this product?",
							new DataCallback<Boolean>(){
								@Override
								public void onCompleted(Boolean data) {
									if (data == Boolean.TRUE){
										deleteProduct();
									}
								}
							}
						);
					}
				}
		));
		toolBar.addPushButton(updateProductBtn = new SimpleRibbonButton("升级产品",
				BoxResources.INSTANCE.updateProduct32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						final Product info = productTable.getSelectedObject();
						if (info != null) {
							SimpleDialog.show(new UpdateProductHandler(info,new Action(){
								@Override
								public void run() {
									loadProducts(info.getCatalogId(), currentOffset);
								}
							}));
						}
					}
				}
		));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(refreshProductBtn = new SimpleRibbonButton("刷新产品",
				CommonResources.INSTANCE.refresh32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						ProductCatalog info = catalogs.getSelectedCatalog();
						if (info != null){
							loadProducts(info.getId(), currentOffset);
						}
					}
				}
		));
		toolBar.addSeparator(ButtonSize.Medium);
		toolBar.addPushButton(previousBtn = new SimpleRibbonButton("前页",
				CommonResources.INSTANCE.prev32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						ProductCatalog info = catalogs.getSelectedCatalog();
						if (info != null) {
							loadProducts(info.getId(), Math.max(currentOffset - MaxRecordsPerPage, 0));
						}
						
					}
				}
		));
		toolBar.addPushButton(nextBtn = new SimpleRibbonButton("后页",
				CommonResources.INSTANCE.next32(),ButtonSize.Medium,
				new WidgetListener(){
					@Override
					public void valueUpdated(Widget widget) {
						ProductCatalog info = catalogs.getSelectedCatalog();
						if (info != null) {
							loadProducts(info.getId(),Math.max(currentOffset + MaxRecordsPerPage, 0));
						}
					}
				}
		));
		
		previousBtn.setEnabled(false);
		nextBtn.setEnabled(false);
		addProductBtn.setEnabled(false);
		deleteProductBtn.setEnabled(false);
		updateProductBtn.setEnabled(false);
		refreshProductBtn.setEnabled(false);
		return toolBar;
	}

	private void createProductCatalogButtons(SimpleRibbon toolBar) {
		toolBar.addPushButton(new SimpleRibbonButton("增加产品类目",
				BoxResources.INSTANCE.addCatalog32(), 
				ButtonSize.Medium,
				new WidgetListener() {
					@Override
					public void valueUpdated(Widget widget) {
						ProductCatalog info = catalogs.getSelectedCatalog();
						if (info != null){
							SimpleDialog.show(new CreateProductCatalogHandler(info, new Action(){
								@Override
								public void run() {
									loadCatalogs();
								}
							}));
						}
					}
				}
		));
		toolBar.addPushButton(deleteCatalogBtn = new SimpleRibbonButton("删除产品类目",
				BoxResources.INSTANCE.deleteCatalog32(),ButtonSize.Medium,
				new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				final ProductCatalog info = catalogs.getSelectedCatalog();
				if (info != null){
					String message = "Delete " + info.getCName() + " will delete all the products under this catalog, are  you sure to do this?";
					SimpleMessageBox.confirm("Delete", message, new DataCallback<Boolean>(){
							@Override
							public void onCompleted(Boolean data) {
								if (data == Boolean.TRUE){
									delete(info);
								}
							}
					});
				}
			}
		}
		));
		toolBar.addPushButton(updateCatalogBtn = new SimpleRibbonButton("升级产品类目",
				BoxResources.INSTANCE.updateCatalog32(),ButtonSize.Medium,
				new WidgetListener(){
			@Override
			public void valueUpdated(Widget widget) {
				ProductCatalog info = catalogs.getSelectedCatalog();
				if (info != null) {
					SimpleDialog.show(new UpdateProductCatalogHandler(info, new Action(){
						@Override
						public void run() {
							loadCatalogs();
						}
					}));
				}
			}
		}
				));
		toolBar.addPushButton(new SimpleRibbonButton("刷新产品类目",
				BoxResources.INSTANCE.refreshCatalog32(),ButtonSize.Medium,
				new WidgetListener(){
				@Override
				public void valueUpdated(Widget widget) {
					updateCatalogBtn.setEnabled(false);
					deleteCatalogBtn.setEnabled(false);
					loadCatalogs();
				}
			}
		));
		toolBar.addSeparator(ButtonSize.Medium);
		deleteCatalogBtn.setEnabled(false);
		updateCatalogBtn.setEnabled(false);
	}
	
	private void deleteProduct() {
		String passport = SessionManager.getPassport();
		Product info = productTable.getSelectedObject();
		final ProductCatalog catalog = catalogs.getSelectedCatalog();
		if (info != null) {
			Services.ProductService.DeleteProduct(passport, info.getProductId(),
				new AsyncCallback<Boolean>(){
					@Override
					public void onFailure(Throwable caught) {
						ErrorHandler.handleServiceError(caught);
					}
					@Override
					public void onSuccess(Boolean result) {
						if (result == Boolean.TRUE){
							loadProducts(catalog.getId(), currentOffset);
						}
					}
				}
			);
		}
	}
	
	protected SplitLayoutPanel createContentPanel() {
		SplitLayoutPanel contentPanel = new SplitLayoutPanel();
		catalogs = new ProductCatalogTree(new DataCallback<ProductCatalog>(){
			@Override
			public void onCompleted(ProductCatalog data) {
				if (data != null) {
					loadProducts(data.getId(), currentOffset);
					refreshProductBtn.setEnabled(true);
					addProductBtn.setEnabled(data.isIsLeaf());	
					if (Session.Current.getRole() == UserRole.SUPER){
						deleteCatalogBtn.setEnabled(true);
						updateCatalogBtn.setEnabled(true);
					}
				}	
			}
		});
		contentPanel.addWest(catalogs, 260);
		contentPanel.add(productTable = ceateTable());
		productTable.getElement().getStyle().setBorderColor("#bbb");
		productTable.getElement().getStyle().setBorderWidth(1, Unit.PX);
		return contentPanel;
	}
	
	private void loadCatalogs() {
		String passport = SessionManager.getPassport();
		SimpleModal.show("Loading Catalogs...");
		Services.ProductCatalogService.GetAllProductCatalogs(passport,
			new AsyncCallback<List<ProductCatalog>>() {
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(List<ProductCatalog> result) {
					SimpleModal.hide();
					SimpleTreeNode node = ProductCatalogTreeUtil.convert(result);
					
					catalogs.clear();
					catalogs.getTree().addNode(node);
					catalogs.getTree().accept(new TreeVisitor<SimpleTreeNode>(){
						@Override
						public boolean VisitLeave(SimpleTreeNode treeNode) {
							return true;
						}
						
						@Override
						public boolean VisitEnter(SimpleTreeNode treeNode) {
							if (!treeNode.isLeaf()){
								 catalogs.getTree().setExpanded(treeNode, true);
							}
							return true;
						}
					});
					addProductBtn.setEnabled(false);
					deleteProductBtn.setEnabled(false);
					updateProductBtn.setEnabled(false);
					refreshProductBtn.setEnabled(false);
				}
			}
		);
	}
	
	private void loadProducts(int catalogId, int offset) {
		String passport = SessionManager.getPassport();
		PagingRequest request = new PagingRequest();
		request.setOffset(offset);
		request.setLimit(MaxRecordsPerPage);
		
		SimpleModal.show("加载产品...");
		Services.ProductService.ListProducts(passport, catalogId, request,
			new AsyncCallback<PagingResult<Product>>(){
				@Override
				public void onFailure(Throwable caught) {
					SimpleModal.hide();
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(PagingResult<Product> result) {
					SimpleModal.hide();
					currentOffset = result.getOffset();
					currentRecordsPerPage = result.getData().size();
					productTableHandler.setObjects(result.getData());
					updateProductBtn.setEnabled(false);
					deleteProductBtn.setEnabled(false);
					previousBtn.setEnabled(result.getOffset()> 0);
					nextBtn.setEnabled(currentRecordsPerPage == result.getData().size() && currentRecordsPerPage != 0);
				}
			}
		);
	}
	
	private void delete(ProductCatalog info) {
		if (!info.isIsLeaf()) {
			 return;
		}
		
		String passport = SessionManager.getPassport();
		Services.ProductCatalogService.RemoveProductCatalog(passport, info.getId(),
			new AsyncCallback<Boolean>(){
				@Override
				public void onFailure(Throwable caught) {
					ErrorHandler.handleServiceError(caught);
				}
				
				@Override
				public void onSuccess(Boolean result) {
					if (result == Boolean.TRUE){
						loadCatalogs();
					}
				}
			}
		);
	}
	
	protected SimpleDataGrid<Product> ceateTable() {
		return new SimpleDataGrid<Product>(
			   MaxRecordsPerPage, 
			   productTableHandler = new ProductTableHandler()
		);
	}
	
	private class ProductLogoRenderer extends CellRenderer<Product> {
		@Override
		public void render(SimpleDataModel<Product> model,
						   ColumnConfig columnConfig, 
						   int rowIndex, 
						   int colIndex,
						   SafeHtmlBuilder sb) {
			sb.append(AbstractImagePrototype.create(BoxResources.INSTANCE.notAvailable()).getSafeHtml());
		}
		
	}
	
	private class ProductTableHandler extends SimpleDataGridHandler<Product> {
		
		private final static String Logo 	  = "Logo";
		private final static String Cname 	  = "Cname";
		private final static String Keywords  = "Keywords";
		private final static String Weight 	  = "Weight";
		private final static String ListOrder = "ListOrder";
		private List<Product> data;

		@Override
		public List<ColumnConfig> createColumns() {
			List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
			configs.add(ColumnConfigs.create(Logo, 	   "产品 Logo", 70, new ProductLogoRenderer()));
			configs.add(ColumnConfigs.create(Cname,    "产品中文名", 100));
			configs.add(ColumnConfigs.create(Keywords, "关键搜索字段", 100));
			configs.add(ColumnConfigs.create(Weight,   "产品重量",  50));
			configs.add(ColumnConfigs.create(ListOrder,"排序号码",  50));
			return configs;
		}

		public void setObjects(List<Product> data2) {
			ProductTableHandler.this.data = data2;
			ProductTableHandler.this.getGrid().setObjects(data2);
		}

		@Override
		public void format(int index, SimpleDataModel<Product> model) {
			Product product = model.getObject();
			model.set(Cname, 	 product.getCName());
			model.set(Keywords,  product.getKeywords());
			model.set(Weight, 	 product.getWeight() + " " + product.getWeightUnit());
			model.set(ListOrder, product.getListOrder());
		}

		@Override
		public List<Product> getObjects() {
			return this.data;
		}

		@Override
		public void onObjectClicked(Product obj) {
			if(obj != null){
				updateProductBtn.setEnabled(true);
				deleteProductBtn.setEnabled(true);
			}
		}

		@Override
		public void onObjectDoubleClicked(Product obj) {
			onObjectClicked(obj);
		}
	}
	
}
